home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
JCSM Shareware Collection 1993 November
/
JCSM Shareware Collection - 1993-11.iso
/
cl720
/
sst115j.lzh
/
SSTWIN.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-18
|
23KB
|
752 lines
/* ------------------------------------------------------------------------ */
/* sstwin.c */
/* high-level window routines */
/* */
/* CopyRight (C) 1991,1992 Steven Lutrov. All rights reserved. */
/* */
/* ------------------------------------------------------------------------ */
#include <stdio.h>
#include <ctype.h>
#include <stdarg.h>
#include <dos.h>
#include <alloc.h>
#include <stdlib.h>
#include <string.h>
#include "sstvid.h"
#include "sstwin.h"
#include "sstedt.h"
#include "sstkey.h"
/* ------------------------------------------------------------------------ */
/* local prototypes */
/* ------------------------------------------------------------------------ */
static void redraw (WINDOW *wnd);
static void wframe (WINDOW *wnd);
static void dtitle (WINDOW *wnd);
static void dfooter (WINDOW *wnd);
static int *waddr (WINDOW *wnd, int x, int y);
static void vswap (WINDOW *wnd);
static void listadd (WINDOW *wnd);
static void listbegin (WINDOW *wnd);
static void listdelete (WINDOW *wnd);
static void listinsert (WINDOW *w1, WINDOW *w2);
static int wpeek (WINDOW *wnd, int x, int y);
static int wndverify (WINDOW **wndc);
void wndrepos (WINDOW *wnd, int x, int y, int z);
/* ------------------------------------------------------------------------ */
/* window structure linked list head & tail */
/* ------------------------------------------------------------------------ */
WINDOW *listhead = NULL; /* head address */
WINDOW *listtail = NULL; /* tail address */
/* ------------------------------------------------------------------------ */
/* array of border character sets */
/* ------------------------------------------------------------------------ */
struct {
unsigned char topleft, topright, botright, botleft, vert, hor;
} wcs[] = {
{ 32, 32, 32, 32, 32, 32}, /* blank line */
{218,191,217,192,179,196}, /* single line */
{201,187,188,200,186,205}, /* double line */
{214,183,189,211,186,196}, /* single top, double side */
{213,184,190,212,179,205}, /* double top, single side */
{194,194,217,192,179,196}, /* single - pop-down menu */
{203,203,188,200,186,205}, /* double - pop-down menu */
{210,210,189,211,186,196}, /* single top pop-down menu */
{209,209,190,212,179,205}, /* double top pop-down menu */
{ 32, 32, 32, 32, 32, 32}, /* blank line */
};
/* ------------------------------------------------------------------------ */
/* establish a new window */
/* ------------------------------------------------------------------------ */
WINDOW *Westablish(int x, int y, int h, int w)
{
WINDOW *wnd;
if ((wnd = (WINDOW *) malloc(sizeof (WINDOW))) == NULL)
return NULL;
WTITLE = "";
WFOOT = "";
TJUST = FJUST = JUST_C;
HEIGHT = min(h, SCREENHEIGHT);
WIDTH = min(w, SCREENWIDTH);
COL = max(0, min(x, SCREENWIDTH-WIDTH));
ROW = max(0, min(y, SCREENHEIGHT-HEIGHT));
WCURS = 0;
SCROLL = 0;
SELECT = 1;
BTYPE = 1;
VISIBLE = HIDDEN = 0;
PREV = NEXT = NULL;
FHEAD = FTAIL = NULL;
WBORDER=WFACE=PWIN_FACE=WTITLEC=WFIELD = CLR(BLACK, WHITE, BRIGHT);
WACCENT = CLR(WHITE, BLACK, DIM);
if ((SAV = (char *)malloc(WIDTH * HEIGHT * 2)) == (char *) 0)
return NULL;
listadd(wnd);
Wclear(wnd);
wframe(wnd);
return wnd;
}
/* ------------------------------------------------------------------------ */
/* set the window's border */
/* ------------------------------------------------------------------------ */
void Wsetborder(WINDOW *wnd, int btype)
{
if (wndverify(&wnd)) {
BTYPE = btype;
wframe(wnd);
redraw(wnd);
}
}
/* ------------------------------------------------------------------------ */
/* set colours */
/* ------------------------------------------------------------------------ */
void Wsetcolour(WINDOW *wnd,int area,int bg,int fg,int inten)
{
if (ISMONO() ) {
if (bg != WHITE && bg != BLACK)
return;
if (fg != WHITE && fg != BLACK)
return;
}
if (wndverify(&wnd)) {
if (area == WIN_ALL)
while (area)
WCOLOUR [--area] = CLR(bg, fg, inten);
else
WCOLOUR [area] = CLR(bg, fg, inten);
redraw(wnd);
}
}
/* ------------------------------------------------------------------------ */
/* set the intensity of a window */
/* ------------------------------------------------------------------------ */
void Wsetintensity(WINDOW *wnd, int inten)
{
int area = WIN_ALL;
if (wndverify(&wnd)) {
while (area) {
WCOLOUR [--area] &= ~BRIGHT;
WCOLOUR [area] |= inten;
}
redraw(wnd);
}
}
/* ------------------------------------------------------------------------ */
/* set title */
/* ------------------------------------------------------------------------ */
void Wsettitle(WINDOW *wnd, char *title, int just)
{
if (wndverify(&wnd)) {
WTITLE = title;
TJUST = just;
redraw(wnd);
}
}
/* ------------------------------------------------------------------------ */
/* set window footer */
/* ------------------------------------------------------------------------ */
void Wsetfooter(WINDOW *wnd, char *s, int j)
{
if (wndverify(&wnd)) {
WFOOT = s;
FJUST = j;
redraw(wnd);
}
}
/* ------------------------------------------------------------------------ */
/* redraw a window when an attribute changes */
/* ------------------------------------------------------------------------ */
static void redraw(WINDOW *wnd)
{
int x, y, chat, atr;
for (y = BORDER_OFFSET; y < HEIGHT-BORDER_OFFSET; y++)
for (x = BORDER_OFFSET; x < WIDTH-BORDER_OFFSET; x++) {
chat = wpeek(wnd, x, y);
atr = (((chat>>8)&255) == PWIN_FACE ? WFACE : WACCENT);
displ(wnd, x, y, chat&255, atr);
}
if (BTYPE != BRD_NOBORDER)
wframe(wnd);
PWIN_FACE = WFACE;
}
/* ------------------------------------------------------------------------ */
/* display an established window */
/* ------------------------------------------------------------------------ */
void Wshow(WINDOW *wnd)
{
if (wndverify(&wnd) && !VISIBLE) {
VISIBLE = 1;
vswap(wnd);
}
}
/* ------------------------------------------------------------------------ */
/* close all windows */
/* ------------------------------------------------------------------------ */
void Wdeleteall()
{
WINDOW *sav, *wnd = listtail;
while (wnd) {
sav = PREV;
Wdelete(wnd);
wnd = sav;
}
}
/* ------------------------------------------------------------------------ */
/* remove a window */
/* ------------------------------------------------------------------------ */
void Wdelete(WINDOW *wnd)
{
if (wndverify(&wnd)) {
Whide(wnd);
free(SAV);
listdelete(wnd); /* remove window from list */
free(wnd);
}
}
/* ------------------------------------------------------------------------ */
/* hide a window */
/* ------------------------------------------------------------------------ */
void Whide(WINDOW *wnd)
{
if (wndverify(&wnd) && VISIBLE) {
vswap(wnd);
HIDDEN = 1;
VISIBLE = 0;
}
}
/* ------------------------------------------------------------------------ */
/* reposition the window in its 3-axis plane */
/* ------------------------------------------------------------------------ */
void wndrepos(WINDOW *wnd, int x, int y, int z)
{
WINDOW *twnd;
int x1, y1, chat;
if (!wndverify(&wnd))
return;
twnd = Westablish(x+COL, y+ROW, HEIGHT, WIDTH);
twnd->_title = WTITLE;
twnd->_tjust = TJUST;
twnd->_footer = WFOOT;
twnd->_fjust = FJUST;
twnd->btype = BTYPE;
twnd->wcolour[WIN_BORDER] = WBORDER;
twnd->wcolour[WIN_TITLE] = WTITLEC;
twnd->wcolour[WIN_ACCENT] = WACCENT;
twnd->wcolour[WIN_FACE] = WFACE;
twnd->_wsp = SCROLL;
twnd->_cr = WCURS;
if (z != 1) {
listdelete(twnd);
if (z == 0)
listinsert(twnd, wnd);
else
listbegin(twnd);
}
for (y1 = 0; y1 < twnd->_wh; y1++)
for (x1 = 0; x1 < twnd->_ww; x1++) {
chat = wpeek(wnd, x1, y1);
displ(twnd, x1, y1, chat&255, (chat>>8)&255);
}
twnd->_wv = 1;
vswap(twnd);
Whide(wnd);
free(SAV);
listdelete(wnd);
*wnd = *twnd;
listinsert(wnd, twnd);
listdelete(twnd);
free(twnd);
}
/* ------------------------------------------------------------------------ */
/* clear the window area */
/* ------------------------------------------------------------------------ */
void Wclear(WINDOW *wnd)
{
register int x1, y1;
if (wndverify(&wnd))
for (y1 = BORDER_OFFSET; y1 < HEIGHT-BORDER_OFFSET; y1++)
for (x1 = BORDER_OFFSET; x1 < WIDTH-BORDER_OFFSET; x1++)
displ(wnd,x1, y1, ' ', WFACE);
}
/* ------------------------------------------------------------------------ */
/* window-oriented printf */
/* ------------------------------------------------------------------------ */
void Wprintf(WINDOW *wnd, char *ln, ...)
{
char dlin [100], *dl = dlin;
if (wndverify(&wnd)) {
va_list ap;
va_start(ap, ln);
vsprintf(dlin, ln, ap);
va_end(ap);
while (*dl)
Wputch(wnd, *dl++);
}
}
/* ------------------------------------------------------------------------ */
/* write a character to the window */
/* ------------------------------------------------------------------------ */
void Wputch(WINDOW *wnd, int c)
{
if (!wndverify(&wnd))
return;
switch (c) {
case '\n':
if (SCROLL == HEIGHT-(2*BORDER_OFFSET)-1)
scroll(wnd, UP);
else
SCROLL++;
WCURS = 0;
break;
case '\t':
do {
displ(wnd,(WCURS++)+BORDER_OFFSET,SCROLL+BORDER_OFFSET,' ',WFACE);
}while ((WCURS%TABS) && (WCURS+BORDER_OFFSET) < WIDTH-(BORDER_OFFSET*2));
break;
default:
if ((WCURS+BORDER_OFFSET) < WIDTH-BORDER_OFFSET) {
displ(wnd, WCURS+BORDER_OFFSET, SCROLL+BORDER_OFFSET, c, WFACE);
WCURS++;
}
break;
}
}
/* ------------------------------------------------------------------------ */
/* write a character and attribute to the window */
/* ------------------------------------------------------------------------ */
void Wputchat(WINDOW *wnd, int c, int bg, int fg, int i)
{
if (!wndverify(&wnd))
return;
switch (c) {
case '\n':
if (SCROLL == HEIGHT-(2*BORDER_OFFSET)-1)
scroll(wnd, UP);
else
SCROLL++;
WCURS = 0;
break;
case '\t':
do {
displ(wnd,(WCURS++)+BORDER_OFFSET,SCROLL+BORDER_OFFSET,' ',WFACE);
}while ((WCURS%TABS) && (WCURS+BORDER_OFFSET) < WIDTH-(BORDER_OFFSET*2));
break;
default:
if ((WCURS+BORDER_OFFSET) < WIDTH-BORDER_OFFSET) {
displ(wnd, WCURS+BORDER_OFFSET, SCROLL+BORDER_OFFSET, c,CLR(bg,fg,i));
WCURS++;
}
break;
}
}
/* ------------------------------------------------------------------------ */
/* set window cursor */
/* ------------------------------------------------------------------------ */
void Wcursor(WINDOW *wnd, int x, int y)
{
if (wndverify(&wnd) &&
x < WIDTH-BORDER_OFFSET && y < HEIGHT-BORDER_OFFSET) {
WCURS = x;
SCROLL = y;
vsetcur(COL+x+BORDER_OFFSET, ROW+y+BORDER_OFFSET);
}
}
/* ------------------------------------------------------------------------ */
/* allow the user to make a window selection */
/* ------------------------------------------------------------------------ */
int Wgetsel(WINDOW *wnd, int s, char *keys)
{
int c = 0, ky;
if (!wndverify(&wnd))
return 0;
SELECT = s;
while (c != ESC && c != '\r' && c != LEFT && c != RIGHT) {
accent(wnd);
c = kgetch();
deaccent(wnd);
switch (c) {
case UP: if (SELECT > 1)
SELECT--;
else
SELECT = SCROLL+1;
break;
case DOWN: if (SELECT < SCROLL+1)
SELECT++;
else
SELECT = 1;
break;
case '\r' :
case ESC :
case RIGHT:
case LEFT : break;
default : if (keys) {
ky = 0;
while (*(keys + ky)) {
if (*(keys+ky)==toupper(c) ||
*(keys+ky)==tolower(c))
return ky + 1;
ky++;
}
}
break;
}
}
return c == '\r' ? SELECT : c == ESC ? 0 : c;
}
union REGS rg;
/* ------------------------------------------------------------------------ */
/* scroll a window's contents up or down */
/* ------------------------------------------------------------------------ */
void scroll(WINDOW *wnd, int dir)
{
int row = HEIGHT-1, col, chat;
if (!wndverify(&wnd))
return;
if (NEXT == NULL && HEIGHT > 3 && VISIBLE) {
rg.h.ah = dir == UP ? 6 : 7;
rg.h.al = 1;
rg.h.bh = WFACE;
rg.h.cl = COL + BORDER_OFFSET;
rg.h.ch = ROW + BORDER_OFFSET;
rg.h.dl = COL + WIDTH - (BORDER_OFFSET+1);
rg.h.dh = ROW + HEIGHT - (BORDER_OFFSET+1);
int86(VIDEO, &rg, &rg);
return;
}
if (dir == UP) {
for (row = 1+BORDER_OFFSET; row < HEIGHT-BORDER_OFFSET; row++)
for (col = BORDER_OFFSET; col < WIDTH-BORDER_OFFSET; col++) {
chat = wpeek(wnd, col, row);
displ(wnd,col,row-1,chat&255,(chat>>8)&255);
}
for (col = BORDER_OFFSET; col < WIDTH-BORDER_OFFSET; col++)
displ(wnd, col, row-1, ' ', WFACE);
}
else {
for (row = HEIGHT-(BORDER_OFFSET+1); row > BORDER_OFFSET; --row)
for (col = BORDER_OFFSET; col < WIDTH-BORDER_OFFSET; col++) {
chat = wpeek(wnd, col, row);
displ(wnd,col,row+1,chat&255,(chat>>8)&255);
}
for (col = BORDER_OFFSET; col < WIDTH-BORDER_OFFSET; col++)
displ(wnd, col, row+1, ' ', WFACE);
}
}
/* ------------------------------------------------------------------------ */
/* draw the window frame */
/* ------------------------------------------------------------------------ */
static void wframe(WINDOW *wnd)
{
register int x, y;
if (!wndverify(&wnd))
return;
/* --------- window title -------------- */
displ(wnd,0, 0, NW, WBORDER);
dtitle(wnd);
displ(wnd,WIDTH-1, 0, NE, WBORDER);
/* ---------- do window sides -------------- */
for (y = 1; y < HEIGHT-1; y++) {
displ(wnd,0, y, SIDE, WBORDER);
displ(wnd,WIDTH-1, y, SIDE, WBORDER);
}
/* --------------- do bottom of frame ---------------- */
displ(wnd,0, y, SW, WBORDER);
for (x = 1; x < WIDTH-1; x++)
displ(wnd,x, y, LINE, WBORDER);
displ(wnd,x, y, SE, WBORDER);
dfooter(wnd);
}
/* ------------------------------------------------------------------------ */
/* display the window title */
/* ------------------------------------------------------------------------ */
static void dtitle(WINDOW *wnd)
{
int x = 1, i, ln;
char *s = WTITLE;
if (!wndverify(&wnd))
return;
switch (TJUST) {
case JUST_L : {
x =1;
while (*s)
displ(wnd, x++, 0, *s++, WTITLEC);
while (x < WIDTH-1)
displ(wnd, x++, 0, LINE, WBORDER);
}
break;
case JUST_R : { i = 1;
while (i < WIDTH-1)
displ(wnd, i++, 0, LINE, WBORDER);
x = ( (WIDTH-1) - strlen(s));
while (*s)
displ(wnd, x++, 0, *s++, WTITLEC);
}
break;
default : if (s) {
ln = strlen(s);
if (ln > WIDTH-2) /* if max screen length -2 */
i = 0;
else
i = ((WIDTH-2-ln) / 2); /* centre */
if (i > 0)
while (i--)
displ(wnd, x++, 0, LINE, WBORDER);
while (*s && x < WIDTH-1)
displ(wnd, x++, 0, *s++, WTITLEC);
}
while (x < WIDTH-1)
displ(wnd, x++, 0, LINE, WBORDER);
} /* switch */
}
/* ------------------------------------------------------------------------ */
/* display the window title */
/* ------------------------------------------------------------------------ */
static void dfooter(WINDOW *wnd)
{
int x = 1, i, ln;
char *s = WFOOT;
if (!wndverify(&wnd))
return;
if (! s)
return;
switch (FJUST) {
case JUST_L : {
x =1;
while (*s)
displ(wnd, x++, HEIGHT-1, *s++, WFOOTC);
while (x < WIDTH-1)
displ(wnd, x++, HEIGHT-1, LINE, WBORDER);
}
break;
case JUST_R : { i = 1;
while (i < WIDTH-1)
displ(wnd, i++, HEIGHT-1, LINE, WBORDER);
x = ( (WIDTH-1) - strlen(s));
while (*s)
displ(wnd, x++, HEIGHT-1, *s++, WFOOTC);
}
break;
default : ln = strlen(s);
if (ln > WIDTH-2) /* if max screen length -2 */
i = 0;
else
i = ((WIDTH-2-ln) / 2); /* centre */
if (i > 0)
while (i--)
displ(wnd, x++, HEIGHT-1, LINE, WBORDER);
while (*s && x < WIDTH-1)
displ(wnd, x++, HEIGHT-1, *s++, WFOOTC);
while (x < WIDTH-1)
displ(wnd, x++, HEIGHT-1, LINE, WBORDER);
} /* switch */
}
/* ------------------------------------------------------------------------ */
/* compute address of a window's display character */
/* ------------------------------------------------------------------------ */
static int *waddr(WINDOW *wnd, int x, int y)
{
WINDOW *nxt = NEXT;
int *vp;
if (!VISIBLE)
return (int *) (SAV+y*(WIDTH*2)+x*2);
x += COL;
y += ROW;
while (nxt) {
if (nxt->_wv)
if (x >= nxt->_wx && x <= nxt->_wx + nxt->_ww-1)
if (y >= nxt->_wy && y <= nxt->_wy + nxt->_wh-1) {
x -= nxt->_wx;
y -= nxt->_wy;
vp = (int *) ((nxt->_ws) +y*(nxt->_ww*2)+x*2);
return vp;
}
nxt = nxt->_nx;
}
return NULL;
}
/* ------------------------------------------------------------------------ */
/* display a character to a window */
/* ------------------------------------------------------------------------ */
void displ(WINDOW *wnd, int x, int y, int ch, int at)
{
int *vp;
int vch = (ch&255)|(at<<8);
if ((vp = waddr(wnd, x, y)) != NULL)
*vp = vch;
else
vputch(x+COL,y+ROW,at,ch);
}
/* ------------------------------------------------------------------------ */
/* get a displayed character from a window */
/* ------------------------------------------------------------------------ */
static int wpeek(WINDOW *wnd, int x, int y)
{
int *vp;
if ((vp = waddr(wnd, x, y)) != NULL)
return *vp;
return (vget(x+COL,y+ROW));
}
/* ------------------------------------------------------------------------ */
/* swap the video image with the save buffer */
/* ------------------------------------------------------------------------ */
static void vswap(WINDOW *wnd)
{
int x, y, chat;
int *bf = (int *) SAV;
for (y = 0; y < HEIGHT; y++)
for (x = 0; x < WIDTH; x++) {
chat = *bf;
*bf++ = wpeek(wnd, x, y);
displ(wnd, x, y, chat&255, (chat>>8)&255);
}
}
/* ------------------------------------------------------------------------ */
/* (de)accent the line where SELECT points */
/* ------------------------------------------------------------------------ */
void acline(WINDOW *wnd, int set)
{
int x, ch;
if (!wndverify(&wnd))
return;
for (x = 1; x < WIDTH - 1; x++) {
ch = wpeek(wnd, x, SELECT) & 255;
displ(wnd, x, SELECT, ch, set);
}
}
/* ------------------------------------------------------------------------ */
/* add a window to the end of the list */
/* ------------------------------------------------------------------------ */
static void listadd(WINDOW *wnd)
{
if (listtail) {
PREV = listtail;
listtail->_nx = wnd;
}
listtail = wnd;
if (!listhead)
listhead = wnd;
}
/* ------------------------------------------------------------------------ */
/* add a window to the beginning of the list */
/* ------------------------------------------------------------------------ */
static void listbegin(WINDOW *wnd)
{
if (listhead) {
NEXT = listhead;
listhead->_pv = wnd;
}
listhead = wnd;
if (!listtail)
listtail = wnd;
}
/* ------------------------------------------------------------------------ */
/* remove a window from the list */
/* ------------------------------------------------------------------------ */
static void listdelete(WINDOW *wnd)
{
if (NEXT)
NEXT->_pv = PREV;
if (PREV)
PREV->_nx = NEXT;
if (listhead == wnd)
listhead = NEXT;
if (listtail == wnd)
listtail = PREV;
NEXT = PREV = NULL;
}
/* ------------------------------------------------------------------------ */
/* insert w1 after w2 */
/* ------------------------------------------------------------------------ */
static void listinsert(WINDOW *w1, WINDOW *w2)
{
w1->_pv = w2;
w1->_nx = w2->_nx;
w2->_nx = w1;
if (w1->_nx == NULL)
listtail = w1;
else
w1->_nx->_pv = w1;
}
/* ------------------------------------------------------------------------ */
/* verify the presence of a window in the list */
/* ------------------------------------------------------------------------ */
static int wndverify(WINDOW **wndc)
{
WINDOW *wnd;
if (*wndc == NULL)
*wndc = listtail;
else {
wnd = listhead;
while (wnd != NULL) {
if (*wndc == wnd)
break;
wnd = NEXT;
}
}
return *wndc != NULL;
}